<?php

namespace app;

use think\db\exception\DataNotFoundException;
use think\db\exception\ModelNotFoundException;
use think\exception\Handle;
use think\exception\HttpException;
use think\exception\HttpResponseException;
use think\exception\ValidateException;
use think\Response;
use Throwable;

/**
 * 应用异常处理类
 */
class ExceptionHandle extends Handle
{
    /**
     * 不需要记录信息（日志）的异常类列表
     * @var array
     */
    protected $ignoreReport = [
        HttpException::class,
        HttpResponseException::class,
        ModelNotFoundException::class,
        DataNotFoundException::class,
        ValidateException::class,
    ];

    /**
     * 记录异常信息（包括日志或者其它方式记录）
     *
     * @access public
     * @param  Throwable $exception
     * @return void
     */
    public function report(Throwable $exception): void
    {
        // 使用内置的方式记录异常日志
        parent::report($exception);
    }

    /**
     * Render an exception into an HTTP response.
     *
     * @access public
     * @param \think\Request   $request
     * @param Throwable $e
     * @return Response
     */
    public function render($request, Throwable $e): Response
    {
        // 添加自定义异常处理机制
        // 为API请求提供友好的JSON格式错误响应
        if ($request->isJson() || $request->header('Accept') === 'application/json') {
            // 验证异常
            if ($e instanceof ValidateException) {
                return json([
                    'code' => 422,
                    'msg'  => '验证失败',
                    'data' => [
                        'errors' => $e->getError()
                    ]
                ])->code(422);
            }

            // 数据未找到异常
            if ($e instanceof DataNotFoundException) {
                return json([
                    'code' => 404,
                    'msg'  => '请求的数据不存在',
                    'data' => []
                ])->code(404);
            }

            // 模型未找到异常
            if ($e instanceof ModelNotFoundException) {
                return json([
                    'code' => 404,
                    'msg'  => '请求的资源不存在',
                    'data' => []
                ])->code(404);
            }

            // HTTP异常
            if ($e instanceof HttpException) {
                switch ($e->getStatusCode()) {
                    case 404:
                        return json([
                            'code' => 404,
                            'msg'  => '请求的资源不存在',
                            'data' => []
                        ])->code(404);
                    case 403:
                        return json([
                            'code' => 403,
                            'msg'  => '权限不足，无法访问',
                            'data' => []
                        ])->code(403);
                    case 401:
                        return json([
                            'code' => 401,
                            'msg'  => '未授权访问',
                            'data' => []
                        ])->code(401);
                    default:
                        return json([
                            'code' => $e->getStatusCode(),
                            'msg'  => $e->getMessage() ?: '请求失败',
                            'data' => []
                        ])->code($e->getStatusCode());
                }
            }

            // 自定义业务异常（如果有的话）
            if (method_exists($e, 'getCode') && method_exists($e, 'getMessage')) {
                $code = $e->getCode();
                // 如果code是正常的状态码范围
                if ($code >= 400 && $code < 600) {
                    return json([
                        'code' => $code,
                        'msg' => $e->getMessage() ?: '请求失败',
                        'data' => []
                    ])->code($code);
                }
            }

            // 其他系统异常
            if (app()->isDebug()) {
                // 调试模式下显示详细错误信息
                return json([
                    'code' => 500,
                    'msg'  => '系统错误：' . $e->getMessage(),
                    'data' => [
                        'file' => $e->getFile(),
                        'line' => $e->getLine(),
                        'trace' => $e->getTrace()
                    ]
                ])->code(500);
            } else {
                // 生产环境下隐藏详细错误信息
                return json([
                    'code' => 500,
                    'msg'  => '系统内部错误，请稍后重试',
                    'data' => []
                ])->code(500);
            }
        }

        // 非API请求交给系统处理
        return parent::render($request, $e);
    }
}
